Ever since Blazor officially came out, I started experimenting with it and learned a lot of things by building projects like Blazor.Diagrams. A lot of us, C# developers, have waited for the ability to create web apps in C# and ditch JavaScript for so long, and Blazor came to the rescue. Although we’re not there yet, things are moving very fast!
This post is the start of a series about Blazor vs React. The main purpose of this series is not to compare Blazor and React, but instead to show how things can be done in both technologies. Hopefully, this will be helpful for React developers that want to try/switch to Blazor.
Introduction
I’m sure most of you are familiar with Blazor and React, but just in case, I’ll introduce the two of them once in this first part of the series:
Blazor
Blazor is a free and open-source web framework that enables developers to create web apps using C# and HTML. It was first created as a prototype/experiment by none other than Steve Sanderson. Blazor has two hosting models:
- Server-Side Blazor: Released as part of .NET Core 3, SSB lets you create web apps that are hosted in ASP.NET Core, where clients send UI updates over a SignalR connection.
- Blazor WebAssembly: Released in May 2020, Blazor Wasm lets you create single-page apps that run directly on the browser using Mono. There is also the ability to do JS Interop.
React
React is an open-source, front end, JavaScript library for building user interfaces or UI components. It was first released by Facebook in May 2013, and has since then become the most popular and used UI library for JavaScript developers.
Context
To keep everything simple and easy to follow, we’ll be making a very basic theme functionality, which contains:
- 2 themes: Dark and Light
- 1 control: Button
The idea here is to be able to set the theme globally and for the controls to style themselves appropriately. In our example, the button should either be black or light.
Since the button can exist in different tree levels, we can’t just pass the current theme through every level/child until the buttons get it. It’s ugly, prone to errors, and unmaintainable. Both Blazor and React have a solution for this, which is what I’ll be showing next.
Here’s what we will be doing:
- Make the current theme available to children at multiple levels
- Style a button depending on the current theme
- Have the ability to change the theme on the fly
React
The Context API is designed to share data that can be considered “global” for a tree of React components. It was introduced in React’s version 16.3.0 and it’s aimed at solving the problem of prop drilling, which is what we’re trying to avoid.
First, we’ll create a context:
Second, we’ll create our button:
As you can see, the button uses the value of the current theme (taken from the context) to style itself. Whenever the value changes, the button will get re-rendered.
Third, we’ll add a way to toggle the dark theme:
setTheme
function, which we will set in the next part.
Finally, we’ll put everything together:
React’s Context API only gives the possibility to share data, but not change it, we need it to handle that ourselves. In this example, we’re using React’s State Hook.
Blazor
CascadingValue
is a component that lets you provide a value to all descendent components, which consume it using the CascadingParameter
attribute.
First, we’ll create our button, which expects the theme to be available:
The CSS is done in a separate file, where it simply uses the button’s class.
Second, we’ll add a way to toggle the dark theme:
As you can see, the ThemeToggler
expects not only the current theme, but also an Action
(method) for it to toggle the themes. This means we need two cascading values.
Finally, we’ll put everything together:
Key difference(s)
The two approaches are very similar, with some differences in the implementation. You need to handle the state in both of them, especially if you want to update the value from a nested child.
However, CascadingValue
has an IsFixed
parameter that tells Blazor to not subscribe the children to updates, as the value will never change, which can be good for performance. React doesn’t seem to have an equivalent option.
Summary
Passing values to all descendent children seems to have a simple and straightforward solution in both Blazor (CascadingValue
and CascadingParameter
) and React (Context API). Even though it might be tempting to use it excessively (e.g. to manage state), you shouldn’t.
References
- https://reactjs.org/docs/context.html#dynamic-context
- https://docs.microsoft.com/en-us/aspnet/core/blazor/components/cascading-values-and-parameters?view=aspnetcore-5.0
You can find the source code of this series in this GitHub Repository.
Feel free to correct me in case I made a mistake, as I’m not that proficient in React.
Happy coding!